<template>
  <ClientOnly>
    <el-button :loading="loading" @click="onExport">导出文章</el-button>
  </ClientOnly>
</template>

<script lang="ts" setup>
import { drawHTML } from 'rasterizehtml'
import { jsPDF } from 'jspdf'
import { ElMessage } from 'element-plus'
import { useToggle } from '@vueuse/core'
import { onMounted } from 'vue'

let drawHTMLInstance: typeof drawHTML

// rasterizehtml 库加载用到了 window 对象
onMounted(() => {
  import('rasterizehtml').then((modules) => {
    drawHTMLInstance = modules.drawHTML
  })
})

type images = {
  image: HTMLImageElement
  svg?: SVGElement
  canvas?: HTMLCanvasElement
}

const [loading, toggle] = useToggle(false)

// 导出
function onExport() {
  toggle(true)
  generateSvg('main')
    .then((images) => scaleImg(images))
    .then(exportPDF)
    .catch(() => {
      ElMessage.error('导出失败，请重试！')
    })
    .finally(() => setTimeout(() => toggle(false), 3000))
}

function onExport1() {
  // html2canvas
}

// 元素生成 svg
function generateSvg(el: string | Element) {
  const target = typeof el === 'string' ? document.querySelector(el) : el
  if (!target) throw new Error('元素不存在！')
  const style = document.querySelectorAll('style')
  const link = document.querySelectorAll('link')
  const container = document.createElement('div')
  style.forEach((item) => container.appendChild(item.cloneNode(true)))
  link.forEach((item) => container.appendChild(item.cloneNode(true)))
  container.append(target.cloneNode(true))

  const canvas = document.createElement('canvas')
  canvas.width = target.clientWidth
  canvas.height = target.clientHeight

  return drawHTMLInstance(container.innerHTML, canvas).then(
    ({ image, svg }) => {
      return { image, svg, canvas }
    }
  )
}

// 导出pdf
function exportPDF({ image }: images) {
  const doc = new jsPDF({ unit: 'pt', format: 'a4' })
  const {
    context2d,
    internal: { pageSize }
  } = doc
  // 页面大小
  const pageWidth = pageSize.width
  const pageHeight = pageSize.height
  const margin = 20

  // 图片适应页面后大小
  const { width, height } = image
  const imgWidth = pageWidth - margin * 2
  const imgHeight = (imgWidth / width) * height

  context2d.autoPaging = true
  context2d.margin = [margin, margin, margin, margin]
  context2d.drawImage(image.src, 0, 0, imgWidth, imgHeight)
  doc.save(`${document.querySelector('h1')?.id || '导出'}.pdf`)
}

function exportByText() {
  const el = document.querySelector('main')
  if (!el) throw new Error('')
  const doc = new jsPDF({ unit: 'pt', format: 'a4', compress: true })
  const {
    context2d,
    internal: { pageSize }
  } = doc
  // 页面大小
  const pageWidth = pageSize.width
  const pageHeight = pageSize.height
  const margin = 20
  doc.setLanguage('zh-CN')
  doc.html(el, {
    margin,
    autoPaging: 'text',
    width: pageWidth - margin * 2,
    windowWidth: pageWidth,
    fontFaces: [
      {
        src: [{ url: 'SourceHanSans-Normal.ttf', format: 'truetype' }],
        family: 'PingFang'
      }
    ],
    callback: (pdf) => {
      pdf.save(`${document.querySelector('h1')?.id || '导出'}.pdf`)
    }
  })
}

// 缩放图片
async function scaleImg(images: images, scale = 2) {
  const canvas = document.createElement('canvas')
  const ctx = canvas.getContext('2d')
  if (!ctx) throw new Error('获取2d画布失败！')
  const { image } = images
  canvas.width = image.width * scale
  canvas.height = image.height * scale
  ctx.drawImage(image, 0, 0, canvas.width, canvas.height)
  image.src = canvas.toDataURL()
  return images
}
</script>

<style lang='scss' scoped></style>